/*******************************************************************************

                   屏幕显示之电子表格单元Demo

本DEMO含lvScrnExcel与TScrnExcel实例
*******************************************************************************/
#include "TExcel_Scrn.h"
#include "TExcel.h"
#include "StringEx.h"
#include <string.h>

/*******************************************************************************
                             TExcel回调实现
*******************************************************************************/
//------------------------------重载页内查找表函数实现----------------------------
//NextStartLine: b15置位表示此行为设备ID，下次需保证查找到内有此ID
//返回实际需装载查找表数量, <= Count
unsigned char TExcel_cbReloadLut(unsigned char Handle,        //句柄
                                  unsigned short NextStartLine,//页内新的起始行
                                  unsigned short *pIdLut,      //需填充的查找表
                                  unsigned char Count)        //需装载查找表数量
{
  return Count;
}

//------------------------填充指定数据行默认颜色---------------------------------
#ifdef SUPPORT_COLOR //支持颜色时 (不调用TExcel_pGetLine()时可实现为空)
#include "Color.h"
void TExcel_cbFullDefaultColor(signed char y)//本页内对应数据行,负为标题
{

}
#endif

//-----------------------------更新指定位置颜色---------------------------------
#ifdef SUPPORT_COLOR //支持颜色时 (不调用TExcel_pGetLine()时可实现为空)
  void TExcel_cbFullColor(unsigned char y,
                          unsigned char x,
                          Color_t *pColorId, //用户指定的颜色ID(非系统色)
                          unsigned char Len)
{

}
#endif

/*******************************************************************************
                        struct _TExcelParaDesc 结构实现
*******************************************************************************/

//-------------------------------参数ID显示信息---------------------------------
static const unsigned char _DispInfo[] = {
     //0售价                 1更新日期               2更新人员
  TEXCEL_ALIGN_L | 0x85, TEXCEL_ALIGN_C | 20,  TEXCEL_ALIGN_C | 10,
     //3序号                  4商品名称              5售价单位
  TEXCEL_ALIGN_L | 4,    TEXCEL_ALIGN_C | 8,  TEXCEL_ALIGN_R | 2,
    //6备注
 TEXCEL_ALIGN_C | 14,
};

//----------------------------得到参数ID标题头字符串------------------------------
static const char *_pGetHeader(unsigned char ParaId)
{
  if(ParaId == 0) return "售价";
  if(ParaId == 1) return "更新日期";
  if(ParaId == 2) return "更新人员";
  if(ParaId == 3) return "序";
  if(ParaId == 4) return "商品名称";
  //if(ParaId == 5) return "";   //售价单位无标题头
  if(ParaId == 6) return "备注";
  return "";
}

//-------------------------得到功能Id对应的字符串显示字符--------------------------
static char _StrBuf[4];
static const char* const _PriceInfo[] = {
 "苹果",   "4.99", "售货员A",  "2025.10.09 15:33:36", "",
 "荔枝",   "9.99", "售货员B",  "2025.10.08 15:32:32", "",
 "特价菜", "1.99", "代售员A",  "2025.10.09 15:35:30", "当日有效",
};

static const char *_pGetData(struct _TExcel *pUi,
                              unsigned short InLine,
                              unsigned char ParaId)
{
  unsigned short Line = InLine + pUi->StartLine;
  if((Line >= 3) && (ParaId != 3)) return "";
  if(ParaId == 0){//售价
    if(Line == 1) TExcel_SetItemColor(pUi, RGBFF0000);//红色着重价格较高
    return _PriceInfo[5 * Line + 1];
  }
  if(ParaId == 1){//更新日期
    if(Line == 2){//特价菜着重当日有效，分别着重日期
      TExcel_SetPerStrColor(pUi, RGBFF00FF, 10);
      TExcel_SetPerStrColor(pUi, RGB0000FF, 8);
    }
    return _PriceInfo[5 * Line + 3];
  }
  if(ParaId == 2)//更新人员
    return _PriceInfo[5 * Line + 2];
  if(ParaId == 3){//序号
    Value2StringFix(InLine + pUi->StartLine + 1, _StrBuf, 2);
    return _StrBuf;
  }
  if(ParaId == 4)//商品名称
    return _PriceInfo[5 * Line + 0];
  if(ParaId == 5)//售价单位
    return "$"; //"¥";
  if(ParaId == 6)//备注
    return _PriceInfo[5 * Line + 4];
 return "";
}

//---------------------------------结构实现--------------------------------------
static const struct _TExcelParaDesc _ParaDesc = {
  _DispInfo, _pGetHeader, _pGetData
};

/*******************************************************************************
                      struct _TExcelStatic 结构实现
*******************************************************************************/

//----------------------------列参数ID查找表-详细信息-----------------------------
//首位为Para长度(b0-6)与颜色标识(b7)，下标(1开始)为列顺序，对应值为参数ID
static const unsigned char _ParaIdLut_Detial[] = {
  0x80 | 7, //总数，表格带颜色
    //序号  商品名称  售价单位  售价  更新人员  更新日期    备注
      3,      4,        5,     0,     2,       1,        6,
};

//----------------------------列参数ID查找表-简要信息-----------------------------
//首位为Para长度(b0-6)与颜色标识(b7)，下标(1开始)为列顺序，对应值为参数ID
static const unsigned char _ParaIdLut_Brief[] = {
  0x80 | 4, //总数，表格带颜色
    //序号  商品名称  售价单位  售价
      3,      4,        5,     0,
};

//-------------------------------得到项总数----------------------------------
//得到项总数,返回负值表示自动从查找表中得出,值仅为参考
static signed short _GetIetmCount(void)
{
  return 100;
}

//---------------------------------结构实现--------------------------------------
const struct _TExcelStatic TExcelStatic_Detial = {//详细信息
  &_ParaDesc,//参数信息描述
  _ParaIdLut_Detial,//列参数ID查找表
  _GetIetmCount,//得到项总数
};

const struct _TExcelStatic TExcelStatic_Brief = {//简要信息
  &_ParaDesc,//参数信息描述
  _ParaIdLut_Brief,//列参数ID查找表
  _GetIetmCount,//得到项总数
};

static const struct _TExcelStatic *const pStaticLUT[] = {
  &TExcelStatic_Detial,   //详细信息
  &TExcelStatic_Brief,    //简要信息
};

/*******************************************************************************
                   struct _lvExcel_ScrnData 结构实现
*******************************************************************************/
#ifdef SUPPORT_LV_EXCEL_DEMO
#include "lvScrnExcel.h"

//---------------------------------MVC结构数据----------------------------------
struct _lvMVC{
   struct _TExcel       Data;       //数据
   struct _lvScrnExcel  Disp;       //显示
   char ContainerStrBuf[64];  //容器时字符串缓冲
};
static struct _lvMVC _lvMVC;

//-------------------更新单元格容器中的行间不同的动态内容--------------------------
static void _UpdateContainerDync(struct _lvScrnExcel *pExcel,
                                lv_obj_t *pContainer,//对应容器
                                unsigned short Col,  //所在列
                                unsigned short Row) //所在行，未转换阵列
{
  //百分比更新
  _lvMVC.ContainerStrBuf[0] = (Row / 10) + '0';
  _lvMVC.ContainerStrBuf[1] = (Row % 10) + '0';
  _lvMVC.ContainerStrBuf[2] = '%';
  _lvMVC.ContainerStrBuf[3] = '\0';
  lv_obj_invalidate(lv_obj_get_child(pContainer, 0)); //更新显示
  //进度条更新
  lv_bar_set_value(lv_obj_get_child(pContainer, 1), Row, LV_ANIM_OFF);
  lv_obj_invalidate(lv_obj_get_child(pContainer, 1)); //更新显示
}

//---------------------------------结构实现--------------------------------------
const struct _lvScrnExcelData lvExcelData =  {
  &_lvMVC,     //挂接的用户数据内容
  NULL,        //确认键回调函数,无时为NULL
  NULL,           //退出回调函数,无时为NULL，此时退出键执行固定回调
  NULL,  //TExcel_Scrn_LineToAryId,   //指定行转换为阵列ID
  NULL,  //TExcel_Scrn_AryIdToLine,   //阵列ID转换为指定行
  _UpdateContainerDync,//更新单元格容器中的行间不同的动态内容
};

#endif // SUPPORT_LV_EXCEL_DEMO
/*******************************************************************************
                   struct _TExcel_ScrnData 结构实现
*******************************************************************************/
#ifdef SUPPORT_TEXCEL_DEMO
#include "TScrnExcel.h"
//---------------------------------MVC结构数据----------------------------------
struct _TMVC{
   struct _TExcel       Data;       //数据
   struct _TScrnExcel   Disp;       //显示
};
static struct _TMVC _TMVC;

//---------------------------------结构实现--------------------------------------
const struct _TScrnExcelData TExcelData =  {
  &_TMVC,                     //挂接的用户数据内容
  NULL,        //确认键回调函数,无时为NULL
  NULL,           //退出回调函数,无时为NULL，此时退出键执行固定回调
  #ifndef SUPPORT_LV_SCRN_EXCEL //LVGL模式直接关连LEXCEL
    TExcel_Scrn_pGetHeader,     //得到标题头
    TExcel_Scrn_GetItemCount,   //得到数据行总数
    TExcel_Scrn_pGetLine,       //得到行数据,返回NULL表示结束
    TExcel_Scrn_UpdateData,    //更新数据(可实现为查找表项)
  #endif
  NULL,  //TExcel_Scrn_LineToAryId,   //指定行转换为阵列ID
  NULL,  //TExcel_Scrn_AryIdToLine,   //阵列ID转换为指定行
};

#endif // SUPPORT_TEXCEL_DEMO
/*******************************************************************************
                           lvScrnExcel_Demo
*******************************************************************************/
#ifdef SUPPORT_LV_EXCEL_DEMO

/*/----------------------------------按键响应回调--------------------------------
static void _BtnEventHandler(lv_event_t *e)
{
  lv_event_code_t Code = lv_event_get_code(e);
  lv_obj_t *obj = lv_event_get_target_obj(e);
}*/

//---------------------------单元器为容器时初始化---------------------------------
static void _CellContainerInit(void)
{
  //备注栏改为容器测试lv_screen_active();
  lv_obj_t *pContainer = lvScrnExcel_CreateContainer(&_lvMVC.Disp, 6, 120, 28);
  //左上为标签
  lv_obj_t *pLabel = lv_label_create(pContainer);
  lv_obj_set_size(pLabel, 32, 20);
  _lvMVC.ContainerStrBuf[0] = '\0';
  lv_label_set_text_static(pLabel, _lvMVC.ContainerStrBuf);
  lv_obj_set_align (pLabel, LV_ALIGN_TOP_LEFT);
  //lv_obj_set_style_border_width(pLabel, 0, LV_PART_MAIN);  // 去边框
  //lv_obj_set_style_outline_width(pLabel, 0, LV_PART_MAIN); // 去边界

  //右下为一个进度条
  lv_obj_t *pBar = lv_bar_create(pContainer);
  lv_obj_set_size(pBar, 100, 10);
  lv_obj_set_align(pBar, LV_ALIGN_BOTTOM_RIGHT);
  lv_obj_set_style_border_width(pBar, 0, LV_PART_MAIN);  // 去边框
  lv_obj_set_style_outline_width(pBar, 0, LV_PART_MAIN); // 去边界

  //左上为一个带字按钮模拟填充色
  lv_obj_t  *pBtn = lv_button_create(pContainer);
  lv_obj_set_size(pBtn, 90, 18);
  lv_obj_set_align(pBtn, LV_ALIGN_TOP_RIGHT);
  lv_obj_clear_flag(pBtn, 0xffff); //禁止焦点等
  lv_obj_set_style_border_width(pBtn, 0, LV_PART_MAIN);  // 去边框
  lv_obj_set_style_outline_width(pBtn, 0, LV_PART_MAIN); // 去边界
  pLabel = lv_label_create(pBtn);
  lv_obj_set_size(pBtn, 80, 17);
  lv_label_set_text(pLabel, "watting...");
  lv_obj_set_align(pLabel, LV_ALIGN_CENTER);
  //lv_obj_add_event_cb(pBtn, _BtnEventHandler, LV_EVENT_CLICKED, &_lvMVC.Disp);
}

//----------------------lvScrnExcel_Demo总对外接口-------------------------------
void lvScrnExcel_Demo(unsigned char ExcelId)
{
  if(ExcelId >= 2) ExcelId = 1;
  //Data初始化
  TExcel_Init(&_lvMVC.Data, ExcelId,  pStaticLUT[ExcelId],  0);
  //UI初始化
  lvScrnExcel_Create(&_lvMVC.Disp, &lvExcelData, lv_screen_active(), 0);
  _CellContainerInit();
  lvScrnExcel_Refurbish(&_lvMVC.Disp); //最后重新刷新
}

//---------------------------外界主动删除实现-------------------------------
void lvScrnExcel_Demo_Delete(void)
{
  lvScrnExcel_Delete(&_lvMVC.Disp);
}

//-----------------------------退出界面回调-------------------------------
//返回0不允许退出
signed char lvScrnExcel_cbQuit(struct _lvScrnExcel *pExcel)
{
  return 1;
}
#endif //SUPPORT_LV_EXCEL_DEMO

/*******************************************************************************
                           TScrnExcel_Demo
*******************************************************************************/
#ifdef SUPPORT_TEXCEL_DEMO

//---------------------TScrnExcel_DemoDemo总对外接口-----------------------------
#ifdef SUPPORT_LV_SCRN_EXCEL
void TScrnExcel_Demo(unsigned char ExcelId)
{
  if(ExcelId >= 2) ExcelId = 1;
  //Data初始化
  TExcel_Init(&_TMVC.Data, ExcelId,  pStaticLUT[ExcelId],  0);
  //UI初始化
  TScrnExcel_Init(&_TMVC.Disp, &TExcelData, lv_screen_active(), 0);
}

//---------------------------外界主动删除实现-------------------------------
void TScrnExcel_Demo_Delete(void)
{
  TScrnExcel_Delete(&_TMVC.Disp);
}

#endif

//-----------------------------退出界面回调-------------------------------
//返回0不允许退出
#ifdef SUPPORT_LV_SCRN_EXCEL
signed char TScrnExcel_cbQuit(struct _TScrnExcel *pExcel)
{
  return 1;
}
#endif

#endif //SUPPORT_TEXCEL_DEMO
